package org.fastsyncer.plugin.impl;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.fastsyncer.common.constant.ConnectorConstant;
import org.fastsyncer.common.entity.DatabaseConfig;
import org.fastsyncer.common.entity.Mapping;
import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.plugin.Convert;
import org.fastsyncer.plugin.impl.pool.DatabasePool;
import org.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * <ul>
 * <dt>港中旅岗位转换规则：</dt>
 *  <dl>
 *      <li>根据人员ID获取企业帐号ID</li>
 *      <li>设置岗位与企业帐号关系中MA_ID属性值为企业帐号ID</li>
 *      <li>根据人员ID修改企业帐号的企业组织</li>
 *  </dl>
 * </ul>
 * 
 * @author AE86
 * @date 2018年01月18日 下午14:27:35
 * @version 1.0.0
 */
public class HongKongPositionConvertImpl extends AbstractHKPositionConvert implements Convert {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private DatabaseConfig cfg;

    @Override
    public String getConvertName() {
        return "港中旅人员异动_用户岗位转换";
    }

    @Override
    public void convert(MappingTask task, List<Map<String, Object>> source, List<Map<String, Object>> target) {
        final int sourceSize = source.size();
        final int targetSize = target.size();
        if (sourceSize != targetSize) {
            return;
        }

        Mapping tm = task.getTargetMapping();
        cfg = (DatabaseConfig) tm.getConfig();
        // 创建连接池
        DatabasePool pool = DatabasePool.getInstance();
        String uuid = pool.create(tm);
        if (StringUtils.isBlank(uuid)) {
            return;
        }
        try {
            Map<String, Object> s;
            Map<String, Object> t;
            for (int i = 0; i < targetSize; i++) {
                s = source.get(i);
                t = target.get(i);
                // 转换数据
                this.execute(uuid, ConnectorConstant.OPERTION_INSERT, s, t);
            }
        } catch (Exception e) {
            logger.info(e.getClass() + " >> " + e.getLocalizedMessage());
        } finally {
            pool.close(uuid);
        }
    }

    @Override
    public void convert(MappingTask task, Map<String, Object> source, Map<String, Object> target, String event, Map<String, Object> beforeData) {
        Mapping tm = task.getTargetMapping();
        cfg = (DatabaseConfig) tm.getConfig();
        DatabasePool pool = DatabasePool.getInstance();
        String uuid = pool.create(tm);
        if (StringUtils.isBlank(uuid)) {
            return;
        }
        try {
            // 转换数据
            this.execute(uuid, event, source, target);
        } catch (Exception e) {
            logger.info(e.getClass() + " >> " + e.getLocalizedMessage());
        } finally {
            pool.close(uuid);
        }
    }

    public void execute(String jdbcTemplateId, String event, Map<String, Object> source, Map<String, Object> target) {
        if (null == target) {
            return;
        }
        // 排除删除操作
        if (ConnectorConstant.OPERTION_DELETE.equals(event)) {
            return;
        }

        DatabasePool pool = DatabasePool.getInstance();
        JdbcTemplate jdbc = pool.get(jdbcTemplateId);
        if (null == jdbc) {
            return;
        }

        // 雇佣编号,0为主岗,1及以上为兼岗
        String emplRcd = source.get("EMPL_RCD").toString();
        // 企业组织ID(单元-部门)
        String baseorgId = new StringBuilder().append(source.get("BUSINESS_UNIT")).append("-").append(source.get("DEPTID")).toString();
        // 人员ID
        String emplId = source.get("EMPLID").toString();
        // 员工类别（港中旅）EMPL_CLASS
        String emplClass = source.get("EMPL_CLASS").toString();
        // 员工状态,A为在职，I为离职
        String emplStatus = source.get("EMPL_STATUS").toString();
        // 员工属性
        Object eAObj = source.get("CTS_EMPL_ATTRI");
        String emplAttri = null == eAObj ? null : eAObj.toString();
        // 员工属性描述
        Object eAdObj = source.get("CTS_EMPL_ATTRIDESC");
        String emplAttriDesc = null == eAdObj ? null : eAdObj.toString();
        // 入职日期 2016-07-30 00:00:00.0
        Timestamp ctsEntryDt = formatTime(source.get("CTS_ENTRY_DT"));
        // 转正日期
        Timestamp ctsToformalDt = formatTime(source.get("CTS_TOFORMAL_DT"));
        // 离职日期
        Timestamp terminationDt = formatTime(source.get("TERMINATION_DT"));

        // 更新企业帐号的组织ID,根据emplId(人员ID)设置岗位与企业帐号关系表的中企业帐号ID
        this.update(jdbc, target, emplRcd, baseorgId, emplId, emplClass, emplStatus, emplAttri, emplAttriDesc, ctsEntryDt, ctsToformalDt, terminationDt);
    }

    private Timestamp formatTime(Object timeStr) {
        if (null != timeStr) {
            String t = timeStr.toString();
            if (StringUtils.isNotBlank(t)) {
                try {
                    long time = ThreadLocalDateUtil.parse(t).getTime();
                    return new Timestamp(time);
                } catch (Exception e) {
                    logger.error("Can not format Timestamp:" + e.getLocalizedMessage());
                }
            }
        }
        return null;
    }

    /**
     * 更新企业帐号的组织ID,根据emplId(人员ID)设置岗位与企业帐号关系表的中企业帐号ID
     * @param jdbc
     * @param target
     * @param emplRcd
     * @param baseorgId 企业组织ID
     * @param emplId
     * @param emplClass 员工类型
     * @param emplStatus 员工状态
     * @param emplAttri 员工属性
     * @param emplAttriDesc 员工属性描述
     * @param ctsEntryDt 入职日期
     * @param ctsToformalDt 转正日期
     * @param terminationDt 离职日期
     */
    private void update(JdbcTemplate jdbc, Map<String, Object> target, String emplRcd, String baseorgId, String emplId, String emplClass, String emplStatus, String emplAttri,
            String emplAttriDesc, Timestamp ctsEntryDt, Timestamp ctsToformalDt, Timestamp terminationDt) {
        // 1.根据人员ID查询sd_ma_account表中的ID
        // 获取企业帐号ID
        String maId = null;
        Map<String, Object> row = null;
        try {
            // SELECT A.ID FROM SD_MA_ACCOUNT A LEFT JOIN SD_BASEORG O ON(A.BASEORG_ID=O.ID) WHERE A.USER_ID = ? AND A.IS_DELETED = '0' 
            row = jdbc.queryForMap(QUERY_ACCOUNT_BY_USER_ID, new Object[] { emplId });
            maId = (String) row.get("ID");
        } catch (DataAccessException e) {
            row = null;
        }
        // 设置人员ID对应的企业帐号ID
        target.put("MA_ID", maId);
        if (StringUtils.isBlank(maId)) {
            super.offer(cfg, emplRcd, baseorgId, emplId, emplClass, emplStatus, emplAttri, emplAttriDesc, ctsEntryDt, ctsToformalDt, terminationDt);
            return;
        }

        // 处理主岗类型数据
        if ("0".equals(emplRcd)) {
            String userStatus = null;
            String accountStatus = null;
            String accountMiStatus = null;
            // 2.处理员工状态 A为在职 I为离职
            if ("A".equalsIgnoreCase(emplStatus)) {
                // 现职
                userStatus = "1";
                // 禁用
                accountStatus = "1";
                // 启用
                accountMiStatus = "1";
            } else if ("I".equalsIgnoreCase(emplStatus)) {
                // 离职
                userStatus = "5";
                // 禁用
                accountStatus = "2";
                // 禁用
                accountMiStatus = "0";
            }
            // 3.根据企业组织ID查询sd_baseorg表中的企业组织名称
            String baseorgName = null;
            try {
                // SELECT BASEORG_NAME FROM SD_BASEORG WHERE ID = ? AND IS_DELETED = '0'
                row = jdbc.queryForMap(QUERY_ORG_BY_ID, new Object[] { baseorgId });
                baseorgName = (String) row.get("BASEORG_NAME");
            } catch (DataAccessException e) {
                row = null;
            }
            // 4.根据人员ID修改sd_user表中的企业组织ID,企业组织名称,员工类型,员工状态,入职日期,转正日期,离职日期
            // UPDATE SD_USER SET BASEORG_ID = ?, BASEORG_NAME = ?, EMPL_CLASS = ?, USER_STATUS = ?, CTS_EMPL_ATTRI = ?, CTS_EMPL_ATTRIDESC = ?, CTS_ENTRY_DT = ?, CTS_TOFORMAL_DT = ?, TERMINATION_DT = ? WHERE ID = ? AND IS_DELETED = '0'
            Object[] args = new Object[] { baseorgId, baseorgName, emplClass, userStatus, emplAttri, emplAttriDesc, ctsEntryDt, ctsToformalDt, terminationDt, emplId };
            int update = jdbc.update(UPDATE_USER_BY_ID, args);
            if (logger.isDebugEnabled()) {
                logger.debug(UPDATE_USER_BY_ID);
                logger.debug(Arrays.toString(args));
                logger.debug("修改sd_user表中的企业组织ID:" + update);
            }
            if (0 == update) {
                super.offer(cfg, emplRcd, baseorgId, emplId, emplClass, emplStatus, emplAttri, emplAttriDesc, ctsEntryDt, ctsToformalDt, terminationDt);
                return;
            }

            // 5.更新企业帐号企业组织ID
            // UPDATE SD_MA_ACCOUNT SET BASEORG_ID = ?, ACCOUNT_STATUS = ? WHERE ID = ? AND IS_DELETED = '0' 
            args = new Object[] { baseorgId, accountStatus, maId };
            update = jdbc.update(UPDATE_ACCOUNT_BY_ID, args);
            if (logger.isDebugEnabled()) {
                logger.debug(UPDATE_ACCOUNT_BY_ID);
                logger.debug(Arrays.toString(args));
                logger.debug("修改企业帐号企业组织ID:" + update);
            }
            // 6.根据企业帐号ID查询关联的应用帐号
            args = new Object[] { baseorgId, maId };
            List<Map<String, Object>> list = jdbc.queryForList(QUERY_MI_ACCOUNT_BY_MA_ID, args);
            if (logger.isDebugEnabled()) {
                logger.debug("根据企业帐号ID查询关联的应用帐号:", QUERY_MI_ACCOUNT_BY_MA_ID);
                logger.debug(Arrays.toString(args));
            }
            // 7.更新应用帐号状态,应用组织,更新时间
            if (null != list && !list.isEmpty()) {
                JSONArray array = new JSONArray();
                for (Map<String, Object> r : list) {
                    Object newAppOrgId = r.get("APPORG_ID");
                    Object miId = r.get("ID");
                    args = new Object[] { newAppOrgId, accountMiStatus, new Timestamp(System.currentTimeMillis()), miId };
                    update = jdbc.update(UPDATE_MI_ACCOUNT_BY_ID, args);
                    if (logger.isDebugEnabled()) {
                        logger.debug(UPDATE_MI_ACCOUNT_BY_ID);
                        logger.debug(Arrays.toString(args));
                        logger.debug("修改应用帐号:{}", update);
                    }
                    row = new HashMap<>();
                    row.put("MA_ID", maId);
                    row.put("MI_ID", miId);
                    row.put("APP_ID", (String) r.get("APP_ID"));
                    row.put("MI_ACCOUNT", (String) r.get("MI_ACCOUNT"));
                    row.put("OLD_APPORG_ID", (String) r.get("OLD_APPORG_ID"));
                    row.put("NEW_APPORG_ID", (String) newAppOrgId);
                    array.put(row);
                }
                // 7.1 将更新的应用帐号通过Http推送给4A
                super.post(array);
            }
        }
        row = null;
    }

}

/**
 * 为解决多线程竞争导致时间转换异常
 * @author AE86
 * @date 2018年5月11日 下午5:31:39
 * @version 1.0.0
 */
class ThreadLocalDateUtil {

    private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>();

    public static DateFormat getDateFormat() {
        DateFormat df = threadLocal.get();
        if (df == null) {
            synchronized (threadLocal) {
                if (df == null) {
                    df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                }
            }
        }
        return df;
    }

    public static Date parse(String strDate) throws ParseException {
        return getDateFormat().parse(strDate);
    };

}
